﻿using In66.Net.Core.System.Extensions.Expressions;
using In66.Net.Repository.IRepositories.ISqlSugar;

namespace Maint.Api.Services.Impl;
public class DictAppService : AbstractAppService, IDictAppService
{
    private readonly ISugarBaseRepository<Dict> _dictRepository;
    private readonly BloomFilterFactory _bloomFilterFactory;
    private readonly CacheService _cacheService;

    public DictAppService(
        ISugarBaseRepository<Dict> dictRepository,
        BloomFilterFactory bloomFilterFactory,
        CacheService cacheService)
    {
        _dictRepository = dictRepository;
        _bloomFilterFactory = bloomFilterFactory;
        _cacheService = cacheService;
    }

    public async Task<AppSrvResult<long>> CreateAsync(DictCreationDto input)
    {
        input.TrimStringFields();
        var exists = await _dictRepository.ExistsAsync(x => x.Name.Equals(input.Name));
        if (exists)
        {
            return Problem(HttpStatusCode.BadRequest, "字典名字已经存在");
        }

        var dists = new List<Dict>();
        long id = IdGenerater.GetNextId();
        var dict = new Dict { Id = id, Name = input.Name, Value = input.Value, Ordinal = input.Ordinal, Pid = 0 };

        dists.Add(dict);
        input.Children?.ForEach(x =>
        {
            dists.Add(new Dict
            {
                Id = IdGenerater.GetNextId(),
                Pid = id,
                Name = x.Name,
                Value = x.Value,
                Ordinal = x.Ordinal
            });
        });

        var cacheKey = _cacheService.ConcatCacheKey(CachingConsts.DictSingleKeyPrefix, id);
        var cahceBf = _bloomFilterFactory.Create(CachingConsts.BloomfilterOfCacheKey);
        var addedStatus = await cahceBf.AddAsync(cacheKey);
        if (!addedStatus)
        {
            return Problem(HttpStatusCode.BadRequest, "添加到布隆过滤器失败!");
        }
        else
        {
            await _dictRepository.InsertAsync(dists);
        }

        return id;
    }

    public async Task<AppSrvResult> UpdateAsync(long id, DictUpdationDto input)
    {
        input.TrimStringFields();

        await _dictRepository.Update(s => s.Id == id, f => new Dict
        {
            Name = input.Name,
            Value = input.Value,
            Ordinal = input.Ordinal
        });

        return AppSrvResult();
    }

    public async Task<AppSrvResult> DeleteAsync(long id)
    {
        await _dictRepository.DeleteAsync(d => (d.Id == id) || (d.Pid == id));
        return AppSrvResult();
    }

    public async Task<DictVo> GetAsync(long id)
    {
        var dictEntity = await _dictRepository.QueryByIdAsync(id);
        if (dictEntity is null)
        {
            return default;
        }

        var dictDto = Mapper.Map<DictVo>(dictEntity);
        var subDictEnties = _dictRepository.QueryListByClause(x => x.Pid == id).ToList();
        if (subDictEnties is not null)
        {
            var subDictDtos = Mapper.Map<List<DictVo>>(subDictEnties);
            dictDto.Children = subDictDtos;
        }
        return dictDto;
    }

    public async Task<List<DictVo>> GetListAsync(DictSearchDto search)
    {
        search.TrimStringFields();

        var result = new List<DictVo>();

        var whereCondition = ExpressionCreator
            .New<Dict>(x => x.Pid == 0)
            .AndIf(search.Name.IsNotNullOrWhiteSpace(), x => SqlFunc.Contains(x.Name, $"{search.Name}%"));

        var dictEntities = _dictRepository
            .QueryListByClause(whereCondition)
            .OrderBy(d => d.Ordinal)
            .ToList();

        if (dictEntities is null)
        {
            return new List<DictVo>();
        }

        var subPids = dictEntities.Select(x => x.Id);
        var allSubDictEntities = _dictRepository.QueryListByClause(x => subPids.Contains(x.Pid)).ToList();

        var dictDtos = Mapper.Map<List<DictVo>>(dictEntities);
        var allSubDictDtos = Mapper.Map<List<DictVo>>(allSubDictEntities);
        foreach (var dto in dictDtos)
        {
            var subDtos = allSubDictDtos?.Where(x => x.Pid == dto.Id).ToList();
            if (subDtos.IsNotNullOrEmpty())
            {
                dto.Children = subDtos;
            }
        }

        return dictDtos;
    }
}